package stud.mpgame.snapshot;

import org.apache.mina.core.buffer.IoBuffer;

import stud.mpgame.network.Message;
import stud.mpgame.network.UserObject;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author f.pavel91@gmail.com
 * @version 1.0
 */
public abstract class ASnapshot extends UserObject implements ISnapshot {

    private Map<Integer, Integer> lastCommandApplyTime = new HashMap<Integer, Integer>();

    private int time;

    protected ASnapshot(int time) {
        this.time = time;
    }

    protected ASnapshot(int deltaTime, ASnapshot previous, List<ICommand> commands) {
        if(previous == null)
            return;

        this.time = previous.time;

        Map< Integer, Integer> previousMap = previous.lastCommandApplyTime;
        for(int userID : previousMap.keySet())
            lastCommandApplyTime.put(userID, previousMap.get(userID));

        for(ICommand command : commands) {
            //System.out.println("ass: " + time + "; " + command.getTime());

            command.apply(previous);
            int userID = command.getUserID();

            lastCommandApplyTime.put(userID, command.getTime());
        }

//        List< IGameObject > gameObjects = previous.getAllGameObjects();
//        for(IGameObject gameObject : gameObjects) {
//            gameObject.model(deltaTime);
//        }
        this.time = previous.time + deltaTime;
    }

    public int getTime() {
        return time;
    }

    @Override
    public void writeExternal(IoBuffer buffer, Message owner) {
        Object userIDAttribute = owner.getFirstSession().getAttribute("userID");
        try {
            if(userIDAttribute == null)
                throw new Exception("session must have an attribute with a user ID");

            int userID = (Integer)userIDAttribute;

            if(!lastCommandApplyTime.containsKey(userID))
                lastCommandApplyTime.put(userID, -1);

            buffer.putInt(lastCommandApplyTime.get(userID));
            buffer.putInt(time);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    abstract public ISnapshot modelNext (int deltaTime, List< ICommand > commands);

    abstract public List< IGameObject > getAllGameObjects();

}
